package com.xh3140.android.widget.chart.flowchart;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.SoundEffectConstants;
import android.view.View;
import android.widget.Checkable;
import android.widget.HorizontalScrollView;

import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;

import com.xh3140.android.widget.R;
import com.xh3140.android.widget.utils.DimenUtils;

import java.util.Objects;

@SuppressWarnings("unused")
public class FlowchartView extends HorizontalScrollView {
    @ColorInt
    private int mDefaultColor;

    @ColorInt
    private int mCheckedColor;

    @Px
    private int mBorderWidth;

    @Px
    private int mBorderRadius;

    @Nullable
    private String mFlowchartList;

    @Nullable
    private ItemView mCheckedView;

    @NonNull
    private final ContentInnerLayout mContentInnerLayout;

    @Nullable
    private OnItemViewCreatedListener mOnItemViewCreatedListener;

    @Nullable
    private OnCheckedChangeListener mOnCheckedChangeListener;

    public interface OnItemViewCreatedListener {
        void onCreated(@NonNull ItemView itemView);
    }

    public interface OnCheckedChangeListener {
        void onCheckedChanged(@NonNull FlowchartView view, @NonNull ItemView itemView, boolean checked);
    }

    public FlowchartView(@NonNull Context context) {
        this(context, null);
    }

    public FlowchartView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowchartView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public FlowchartView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowchartView, 0, 0);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            saveAttributeDataForStyleable(context, R.styleable.FlowchartView, attrs, a, defStyleAttr, 0);
        }
        try {
            mDefaultColor = a.getColor(R.styleable.FlowchartView_default_color, 0xFF1C1C1C);
            mCheckedColor = a.getColor(R.styleable.FlowchartView_checked_color, 0xFFFF4500);
            mBorderWidth = a.getDimensionPixelSize(R.styleable.FlowchartView_border_width, DimenUtils.dp2px(context, 2));
            mBorderRadius = a.getDimensionPixelSize(R.styleable.FlowchartView_border_radius, DimenUtils.dp2px(context, 8));
            mFlowchartList = a.getString(R.styleable.FlowchartView_flowchart_list);
        } finally {
            a.recycle();
        }
        mContentInnerLayout = new ContentInnerLayout(context);
        if (mFlowchartList != null) {
            final String[] texts = mFlowchartList.split("->");
            for (String text : texts) {
                mContentInnerLayout.addFlowChildView(text);
            }
        }
        addView(mContentInnerLayout, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
        setHorizontalScrollBarEnabled(false);
    }

    public void setCheckedView(int index) {
        setCheckedView((ItemView) mContentInnerLayout.getChildAt(index));
    }

    private void setCheckedView(@Nullable ItemView view) {
        if (mCheckedView != view) {
            if (mCheckedView != null) {
                mCheckedView.setChecked(false);
            }
            mCheckedView = view;
            if (mCheckedView != null && !mCheckedView.isChecked()) {
                mCheckedView.setChecked(true);
            }
        }
    }

    public class ItemView extends AppCompatTextView implements Checkable {
        private boolean mChecked;
        private final int mPosition;

        private ItemView(@NonNull Context context, int position, @Nullable CharSequence text) {
            super(context);
            setFocusable(true);
            setClickable(true);
            setGravity(Gravity.CENTER);
            setTextSize(Color.BLACK);
            setTextSize(16f);
            int padding = DimenUtils.dp2px(context, 8);
            setPaddingRelative(padding, padding, padding, padding);
            updateView();
            setText(text);
            mPosition = position;
            if (mOnItemViewCreatedListener != null) {
                mOnItemViewCreatedListener.onCreated(this);
            }
        }

        public void updateView() {
            setTextColor(mChecked ? mCheckedColor : mDefaultColor);
            final GradientDrawable drawable = new GradientDrawable();
            drawable.setStroke(mBorderWidth, mChecked ? mCheckedColor : mDefaultColor);
            drawable.setCornerRadius(mBorderRadius);
            setBackground(drawable);
        }

        @Override
        public void setChecked(boolean checked) {
            if (mChecked != checked) {
                mChecked = checked;
                if (checked) {
                    setCheckedView(this);
                }
                updateView();
                if (mOnCheckedChangeListener != null) {
                    mOnCheckedChangeListener.onCheckedChanged(FlowchartView.this, this, checked);
                }
            }
        }

        @Override
        public boolean isChecked() {
            return mChecked;
        }

        @Override
        public void toggle() {
            if (!isChecked()) {
                setChecked(!mChecked);
            }
        }

        @Override
        public boolean performClick() {
            toggle();
            final boolean handled = super.performClick();
            if (!handled) {
                playSoundEffect(SoundEffectConstants.CLICK);
            }
            return handled;
        }

        public int getPosition() {
            return mPosition;
        }
    }

    private class ContentInnerLayout extends LinearLayoutCompat {

        public ContentInnerLayout(@NonNull Context context) {
            super(context);
            setOrientation(LinearLayoutCompat.HORIZONTAL);
            setShowDividers(LinearLayoutCompat.SHOW_DIVIDER_MIDDLE);
            updateDivider();
        }

        public void updateDivider() {
            final VectorDrawableCompat divider = VectorDrawableCompat.create(getResources(), R.drawable.divider_flowchart_arrow, getContext().getTheme());
            if (divider != null) {
                divider.setTint(mDefaultColor);
                setDividerDrawable(new InsetDrawable(divider, DimenUtils.dp2px(getContext(), 4)));
            }
        }

        public void updateAllChildViews() {
            final int childCount = getChildCount();
            for (int i = 0; i < childCount; ++i) {
                final View child = getChildAt(i);
                if (child instanceof ItemView) {
                    ((ItemView) child).updateView();
                }
            }
        }

        public void addFlowChildView(@Nullable String text) {
            final int position = getChildCount();
            final ItemView itemView = new ItemView(getContext(), position, text);
            if (itemView.isChecked()) {
                setCheckedView(itemView);
            }
            addView(itemView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        }
    }

    @ColorInt
    public int getDefaultColor() {
        return mDefaultColor;
    }

    public void setDefaultColor(@ColorInt int color) {
        if (mDefaultColor != color) {
            mDefaultColor = color;
            mContentInnerLayout.updateDivider();
            mContentInnerLayout.updateAllChildViews();
        }
    }

    @ColorInt
    public int getCheckedColor() {
        return mCheckedColor;
    }

    public void setCheckedColor(int color) {
        if (mCheckedColor != color) {
            mCheckedColor = color;
            mContentInnerLayout.updateAllChildViews();
        }
    }

    @Px
    public int getBorderWidth() {
        return mBorderWidth;
    }

    public void setBorderWidth(@Px int width) {
        if (mBorderWidth != width) {
            mBorderWidth = width;
            mContentInnerLayout.updateAllChildViews();
        }
    }

    @Px
    public int getBorderRadius() {
        return mBorderRadius;
    }

    public void setBorderRadius(@Px int radius) {
        if (mBorderRadius != radius) {
            mBorderRadius = radius;
            mContentInnerLayout.updateAllChildViews();
        }
    }

    @Nullable
    public String getFlowchartList() {
        return mFlowchartList;
    }

    public void setFlowchartList(@Nullable String flowchartList) {
        if (!Objects.equals(mFlowchartList, flowchartList)) {
            mFlowchartList = flowchartList;
            mContentInnerLayout.removeAllViews();
            if (mFlowchartList != null) {
                final String[] texts = mFlowchartList.split("->");
                for (String text : texts) {
                    mContentInnerLayout.addFlowChildView(text);
                }
            }
        }
    }

    public void setOnItemViewCreatedListener(@Nullable OnItemViewCreatedListener listener) {
        mOnItemViewCreatedListener = listener;
    }

    public void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) {
        mOnCheckedChangeListener = listener;
    }
}
